﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using InsuranceCompany.Core.Domain.Objects;
using InsuranceCompany.Core.Domain.InsuranceArea;

namespace InsuranceCompany.Core.Domain.InsuranceObjects
{
    public class Policy : Document
    {
        public InsuranceType Type { get; set; }
        private Decimal insuranceSum;
        public Decimal InsuranceSum 
        {
            get
            {
                return insuranceSum;
            }
            set
            {
                this.resetErrorMessage();
                if (Type == null)
                {
                    this.setErrorMessage("Insurance type wasn't choosed");
                    return;
                }
                if (value > Type.RiskMaxSum)
                {
                    this.setErrorMessage("Entering value greater then maximal insurance sum of current type");
                    return;
                }
                //*/
                insuranceSum = value;
                //RestSum = InsuranceSum;
            }
        }

        private int policyPeriod;
        public int PolicyPeriod 
        {
            get
            {
                return policyPeriod;
            }
            set
            {
                this.resetErrorMessage();
                if (Type == null)
                {
                    this.setErrorMessage("Insurance type wasn't choosed");
                    return;
                }
                if (value.CompareTo(Type.MinContractTime) == -1)
                {
                    this.setErrorMessage("Entering value less then minimal period of current type");
                    return;
                }
                if (value.CompareTo(Type.MaxContractTime) == 1)
                {
                    this.setErrorMessage("Entering value greater then maximal period of current type");
                    return;
                }
                //*/
                policyPeriod = value;
            }
        }

        private InsuranceRisks Risks;

        private Decimal price;
        public Decimal Price 
        { 
            get
            {
                return price;
            }
            set 
            {
                this.resetErrorMessage();
                if (Type == null)
                {
                    this.setErrorMessage("Insurance type wasn't choosed");
                    return;
                }
                if (value < Type.MinCost)
                {
                    this.setErrorMessage("Entering value less then minimal price of current type");
                    return;
                }
                //*/
                price = value;
            }
        }

        //private Decimal RestSum;      
         
        private History History;

        public Policy() :base()
        {
            Type = null;
            InsuranceSum = 0.0M;
            PolicyPeriod = 0;
            Risks = null;
            Price = 0.0M;
            //RestSum = 0.0M;
            History = new History();
            History.AddEvent(new InsuranceEvent(DateTime.Today, "Policy registration", null));
        }

        public Policy(Policy p)
            : base(p)
        {
            Type = new InsuranceType(p.Type);
            InsuranceSum = p.InsuranceSum;
            PolicyPeriod = p.PolicyPeriod;
            Risks = new InsuranceRisks(p.GetRisks());
            Price = p.Price;
            //RestSum = p.GetRestSum();
            History = p.History;
        }

        public Policy(Client.Client client, String insObject, DateTime createDate, Employee employee, 
                      InsuranceType type, Decimal insuranceSum, int policyPeriod, InsuranceRisks risks, Decimal price)
            : base(client, insObject, createDate, employee)
        {
            Type = type;
            InsuranceSum = insuranceSum;
            PolicyPeriod = policyPeriod;
            Risks = risks;
            Price = price;
            //RestSum = InsuranceSum;
            History = new History();
            History.AddEvent(new InsuranceEvent(DateTime.Today, "Policy registration", null));
        }

        public Policy(Document doc, InsuranceType type, Decimal insuranceSum, int policyPeriod, InsuranceRisks risks, Decimal price)
            : base(doc)
        {
            Type = type;
            InsuranceSum = insuranceSum;
            PolicyPeriod = policyPeriod;
            Risks = risks;
            Price = price;
            //RestSum = InsuranceSum;
            History = new History();
            History.AddEvent(new InsuranceEvent(DateTime.Today, "Policy registration", null));
        }
        public History GetHistory	() {return this.History;}
        public void AddEvent(Event ev) {this.History.AddEvent(ev);}
        public void AddRisk(InsuranceRisk risk) 
        { 
            this.resetErrorMessage(); 
            if (!Type.ContainsRisk(risk))
            {
                this.setErrorMessage("Entering value doesn't presents in current type!");
                return;
            }
            this.Risks.AddRisk(risk); 
        }
        public void ReplaceRisks(InsuranceRisks risks)
        {
            Risks.ReplaceRisks(risks);
        }
        public void ReplaceRisks(List<InsuranceRisk> risks)
        {
            Risks.ReplaceRisks(risks);
        }
        public InsuranceRisk GetRisk(int riskIndex) {return this.Risks.GetRisk(riskIndex);}
        public InsuranceRisks GetRisks() { return this.Risks; }
        public void DeleteRisk(int riskIndex) { this.Risks.DeleteRisk(riskIndex); }
        public void DeleteAllRisks() { this.Risks.DeleteAll(); }
        public Decimal GetRestSum() 
        {
            Decimal RestSum = InsuranceSum;
            foreach (var ev in this.GetHistory().GetHistory())
            {
                InsuranceEvent iev = (InsuranceEvent) ev;
                if (iev.Document == null)
                    continue;
                Accident acc = (Accident)iev.Document;
                if (acc.Result == "Принято")
                    RestSum -= acc.GetPaymentSum();
            }
            return RestSum; 
        }
        public bool GetStatus()
        {
            TimeSpan tmp = DateTime.Today.Subtract(new DateTime(1,0,0));
            DateTime dateDiff = CreateDate.Subtract(tmp + new TimeSpan(365,0,0,0,0));
            if ((dateDiff.Month - PolicyPeriod) > 0)
                return false;
            else
                return true;
        }
        public void CountAccident(Accident accident) 
        {
            InsuranceEvent currEvent = new InsuranceEvent(accident.AccidentDate, accident.Description, accident);
            if (this.History.GetHistory().Contains(currEvent))
                return;
            //RestSum -= accident.GetPaymentSum();
            this.History.AddEvent(currEvent);
            this.History.AddEvent(new InsuranceEvent(DateTime.Today, "Payment: payment sum = " + accident.GetPaymentSum() + 
                                                                        ", rest sum = " + this.GetRestSum(), accident));
        }

    }
}
